use privacy_for_extensibility::{
    self,
    a::{
        self, create_mod_a_s, create_variant_a, create_variant_b, create_variant_c,
        create_variant_d, AdmitMoreVariants,
    },
    b::{self, create_mod_b_s},
};

#[allow(unused_variables)]
pub fn name_matched_variant(variant: AdmitMoreVariants) -> String {
    match variant {
        AdmitMoreVariants::VariantA => "it's an A".to_string(),
        AdmitMoreVariants::VariantB => "it's a B".to_string(),
        // .. is required because this variant is non-exhaustive as well.
        AdmitMoreVariants::VariantC { a, .. } => "it's a C".to_string(),
        // The wildcard match is required because more variants may be
        // added in the future.
        _ => "it's a new variant".to_string(),
    }
}

fn main() {
    // Non-exhaustive structs cannot be constructed as normal outside the defining crate.
    // let s = a::S {
    //     field: 1,
    //     new_field: 2,
    // };

    let s = create_mod_a_s(1);
    assert_eq!(1, s.field);
    assert_eq!(0, s.new_field);

    // Because S is `#[non_exhaustive]`, it cannot
    // be named here and we must use `..` in the pattern.
    let a::S {
        field: field_copy, ..
    } = s;
    assert_eq!(1, field_copy);

    let res = name_matched_variant(create_variant_a());
    assert_eq!("it's an A".to_string(), res);

    let res = name_matched_variant(create_variant_b());
    assert_eq!("it's a B".to_string(), res);

    let res = name_matched_variant(create_variant_c());
    assert_eq!("it's a C".to_string(), res);

    let res = name_matched_variant(create_variant_d());
    assert_eq!("it's a new variant".to_string(), res);

    // Structs with private fields cannot be constructed as normal outside the
    // defining module.
    // let s = b::S {
    //     a: 1,
    // };

    let s = create_mod_b_s(1);
    assert_eq!(1, s.a);

    let b::S { a: a_copy, .. } = s;
    assert_eq!(1, a_copy);
}
